package dgut.party.business.service.impl.user;

import dgut.party.business.dao.MenuRepository;
import dgut.party.business.dao.user.AccountRepository;
import dgut.party.business.entity.base.Account;
import dgut.party.business.entity.base.Menu;
import dgut.party.business.service.user.AccountRetrieveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true)
public class AccountServiceImpl implements AccountRetrieveService {

  @Autowired
  AccountRepository accountRepo;

  @Autowired
  MenuRepository menuRepo;

  @Override
  public Account findByUsernameOrPhone(String usernameOrPhone) {
    List<Account> accounts = accountRepo.findByUsernameOrPhone(usernameOrPhone, usernameOrPhone);
    if (accounts.size() > 1)
      throw new RuntimeException("用户名或手机号码不唯一");
    else if (accounts.size() == 0)
      return null;
    return accounts.get(0);
  }

  @Override
  public Menu findAccountMenuTree(String username) {
    Account account = this.findByUsernameOrPhone(username);
    return this.findAccountMenuTree(account.getId());
  }

  @Override
  public Menu findAccountMenuTree(long userId) {
    Set<String> authSet = this.findAccountAuthorities(userId);
    Menu rootMenu = menuRepo.findByName("menu_root");
    return filterMenu(rootMenu, authSet);
  }

  private Menu filterMenu(Menu menu, Set<String> authSet) {
    List<Menu> afterFilt = menu.getSubMenus().stream()
      .filter(sub -> {
        if (sub == null || sub.getAuth() == null) return false;
        return authSet.contains(sub.getAuth().getName());
      })
      .map(sub -> this.filterMenu(sub, authSet))
      .collect(Collectors.toList());
    menu.setSubMenus(afterFilt);
    return menu;
  }

  @Override
  public Set<String> findAccountAuthorities(long userId) {
    Set<String> authSet = new HashSet<String>();
    Account account = accountRepo.findById(userId).orElseThrow(() -> new RuntimeException("没有此用户"));
    account.getRoles().forEach(role -> {
      role.getAuthorities().forEach(auth -> {
        authSet.add(auth.getName());
      });
    });
    return authSet;
  }

}
